/*
 * UWT 2014
 */
package database;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import controller.VisualCandoControls;

public final class CreateCandoTable {
	private static final Logger logger = LoggerFactory.getLogger(CreateCandoTable.class);
	
	//Static variables for cando table
	/**
	 * Name of column one.
	 */
	public static final String COLUMN_ONE_NAME = "Protein ID";
	/**
	 * Column one type.
	 */
	private static final String COLUMN_ONE_TYPE = "VARCHAR(20) NOT NULL";
	
	/**
	 * Name of column two.
	 */
	public static final String COLUMN_TWO_NAME = "Protein Number";
	/**
	 * Column two type.
	 */
	private static final String COLUMN_TWO_TYPE = "INTEGER NOT NULL";
	
	/**
	 * Compound column type.
	 */
	private static final String COMPOUND_COLUMN_TYPE = "DOUBLE NOT NULL DEFAULT 0";
	
	/**
	 * Primary key of table.
	 */
	private static final String PRIMARY_KEY = COLUMN_TWO_NAME;
	
	/**
	 * Total number of compounds.
	 */
	private final int numTotalCompounds;
	
	/**
	 * Total number of vertical partitions.
	 */
	private final int numVerticalPartitions;
	
	/**
	 * Schema name.
	 */
	private final String schema;
	
	/**
	 * Table name.
	 */
	private final String tableName;
	
	/**
	 * Database connection.
	 */
	private final CandoDatabase db;
	
	/**
	 * Main to run CreateCandoTable object.
	 * @param args main arguments.
	 */
	public static void main(String[] args) {
		final CandoDatabase db = new CandoDatabase(new VisualCandoControls());
		final CreateCandoTable createTable = new CreateCandoTable(db);
		
		for (int i = 0; i < db.getNumVerticalPartitions(); i++) {
			db.executeScript(createTable.withPartitions(i));
			logger.info("Table partition {} creation SUCCESS.", i);
		}
		logger.info("All {} table partitions created successfully.", db.getNumVerticalPartitions());
	}
	
	/**
	 * Constructs CreateCandoTable object.
	 * @param db Database connection.
	 */
	public CreateCandoTable(CandoDatabase db) {
		this.db = db;
		this.numTotalCompounds = this.db.getNumCompounds();
		this.numVerticalPartitions = this.db.getNumVerticalPartitions();
		this.schema = "`" + this.db.getSchema() + "`";
		this.tableName = this.db.getCandoTableName();	
	}
	
	/**
	 * Returns SQL script for creating a table with the specified partition number.
	 * 
	 * @param partitionNumber Partition number of table.
	 * @return Returns script to generate table in SQL database.
	 */
	public String withPartitions(final int partitionNumber) {
		logger.info("CREATING table: {}", this.tableName + "_" + (partitionNumber + 1));
		final StringBuilder sb = new StringBuilder();
		sb.append("CREATE TABLE ");
		sb.append(this.schema);
		sb.append(".");
		sb.append("`" + this.tableName + "_" + (partitionNumber + 1) + "`");
		sb.append(" (");
		sb.append("`" + COLUMN_ONE_NAME + "` " + COLUMN_ONE_TYPE + ", ");
		sb.append("`" + COLUMN_TWO_NAME + "` " + COLUMN_TWO_TYPE + ", ");
		
		//Establishes the range of compounds assigned to this partition
		final int partitionCompoundRange = this.numTotalCompounds / this.numVerticalPartitions;
		final int compoundStart = partitionNumber * partitionCompoundRange + 1;
		int compoundEnd = partitionNumber * partitionCompoundRange + partitionCompoundRange;
		
		if (partitionNumber == this.numVerticalPartitions - 1) {
			compoundEnd += (this.numTotalCompounds % this.numVerticalPartitions);
		}
	
		for (int i = compoundStart; i <= compoundEnd; i++) {

			sb.append("`" + i + "` " + COMPOUND_COLUMN_TYPE + ", ");
		}		
		sb.append("PRIMARY KEY " + "(`" + PRIMARY_KEY + "`));");
		
		return sb.toString();	
	}
}
